package com.zdkj.subway.rca.controller;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.zdkj.common.core.util.R;
import com.zdkj.common.log.annotation.SysLog;
import com.zdkj.subway.rca.mapper.SwCkItvmSubAccountDataReviewVOMapper;
import com.zdkj.subway.rca.util.LocalDateConverter;
import com.zdkj.subway.rca.util.LocalDateTimeConverter;
import com.zdkj.subway.rca.util.MyDateUtil;
import com.zdkj.subway.rca.vo.SwCkItvmSubAccountDataReviewVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author lu
 * @Date 2021-09-07
 * 数据关联性审核-ITVM分账户数据复核表
 */
@RestController
@AllArgsConstructor
@RequestMapping("/swckitvmsubaccountdatareview" )
@Api(value = "swckitvmsubaccountdatareview", tags = "数据关联性审核-ITVM分账户数据复核表")
public class SwCkItvmSubAccountDataReviewVOController {
    private static final Logger LOGGER = LoggerFactory.getLogger(SwCkItvmSubAccountDataReviewVOController.class);
    private SwCkItvmSubAccountDataReviewVOMapper swCkItvmSubAccountDataReviewVOMapper;
    /**
     * 分页查询
     * @param
     * @return
     */
    @ApiOperation(value = "分页查询,startDate 格式：yyyy-MM-dd, endDate 格式： yyyy-MM-dd", notes = "分页查询")
    @GetMapping("/list" )
    @ApiImplicitParams(
            {
                    @ApiImplicitParam(name = "startDate", value = "开始日期：yyyy-MM-dd", dataTypeClass = String.class,required = true),
                    @ApiImplicitParam(name = "endDate", value = "结束日期：yyyy-MM-dd", dataTypeClass = String.class,required = true),
            }
    )
    public R getSwCkClearEmergencyReturnticketList(String startDate, String endDate) throws Exception {
        if(StringUtils.isEmpty(startDate) ||  StringUtils.isEmpty(endDate)){
            return R.failed("开始日期和结束日期不能为空");
        }
        List<SwCkItvmSubAccountDataReviewVO> list = new ArrayList<>();
        //获取时间段内的日期集合
        List<String> datesBetweenTwoDate = MyDateUtil.getDatesBetweenTwoDate(startDate, endDate);
        for (String s : datesBetweenTwoDate) {
            SwCkItvmSubAccountDataReviewVO dataReviewVO = new SwCkItvmSubAccountDataReviewVO();
            dataReviewVO.setTradeDate(MyDateUtil.StringTurnLocalDate(s));
            list.add(dataReviewVO);
        }

        //对账 125914号线的支付宝和346号线的支付宝
        List<SwCkItvmSubAccountDataReviewVO> reconciliationAlipayList = swCkItvmSubAccountDataReviewVOMapper.getReconciliationAlipay(startDate,endDate);
        if(CollectionUtil.isNotEmpty(reconciliationAlipayList)){
            list.addAll(reconciliationAlipayList);
        }
        //对账 125914号线的微信和346号线的微信
        List<SwCkItvmSubAccountDataReviewVO> reconciliationWeChatList = swCkItvmSubAccountDataReviewVOMapper.getReconciliationWeChat(startDate,endDate);
        if(CollectionUtil.isNotEmpty(reconciliationWeChatList)){
            list.addAll(reconciliationWeChatList);
        }
        //调账 12514号线的支付宝和微信
        List<SwCkItvmSubAccountDataReviewVO> adjustAList = swCkItvmSubAccountDataReviewVOMapper.getAdjustA(startDate,endDate);
        if(CollectionUtil.isNotEmpty(adjustAList)){
            list.addAll(adjustAList);
        }
        //调账 346号线的支付宝和微信
        List<SwCkItvmSubAccountDataReviewVO> adjustBList = swCkItvmSubAccountDataReviewVOMapper.getAdjustB(startDate,endDate);
        if(CollectionUtil.isNotEmpty(adjustBList)){
            list.addAll(adjustBList);
        }
        //调账 9号线的支付宝和微信 最后和 调账 12514号线 各自的支付宝和微信合并到一起
        List<SwCkItvmSubAccountDataReviewVO> adjustCList = swCkItvmSubAccountDataReviewVOMapper.getAdjustC(startDate,endDate);
        if(CollectionUtil.isNotEmpty(adjustCList)){
            list.addAll(adjustCList);
        }
        //根据日期分组统计
        List<SwCkItvmSubAccountDataReviewVO> newList = new ArrayList<>();
        Map<LocalDate, List<SwCkItvmSubAccountDataReviewVO>> collectMap = list.stream().collect(Collectors.groupingBy(swKey -> swKey.getTradeDate()));
        Set<LocalDate> keySet = collectMap.keySet();
        for (LocalDate key : keySet) {
            List<SwCkItvmSubAccountDataReviewVO> vos = collectMap.get(key);
            if(CollectionUtil.isNotEmpty(vos)){
                SwCkItvmSubAccountDataReviewVO reviewVO = new SwCkItvmSubAccountDataReviewVO();
                reviewVO.setTradeDate(key);
                for (SwCkItvmSubAccountDataReviewVO vo : vos) {
                    ////////一二五九十四号线////////
                    //TVM支付宝
                    reviewVO.setTvmAlipayA(ifNullDecimal(reviewVO.getTvmAlipayA()).add(ifNullDecimal(vo.getTvmAlipayA())));
                    //TVM微信
                    reviewVO.setTvmWeChatA(ifNullDecimal(reviewVO.getTvmWeChatA()).add(ifNullDecimal(vo.getTvmWeChatA())));
                    //TVM对账支付宝
                    reviewVO.setTvmReconciliationAlipayA(ifNullDecimal(reviewVO.getTvmReconciliationAlipayA()).add(ifNullDecimal(vo.getTvmReconciliationAlipayA())));
                    //TVM对账微信
                    reviewVO.setTvmReconciliationWeChatA(ifNullDecimal(reviewVO.getTvmReconciliationWeChatA()).add(ifNullDecimal(vo.getTvmReconciliationWeChatA())));

                    ////////三四六号线////////
                    //TVM支付宝
                    reviewVO.setTvmAlipayB(ifNullDecimal(reviewVO.getTvmAlipayB()).add(ifNullDecimal(vo.getTvmAlipayB())));
                    //TVM微信
                    reviewVO.setTvmWeChatB(ifNullDecimal(reviewVO.getTvmWeChatB()).add(ifNullDecimal(vo.getTvmWeChatB())));
                    //TVM对账支付宝
                    reviewVO.setTvmReconciliationAlipayB(ifNullDecimal(reviewVO.getTvmReconciliationAlipayB()).add(ifNullDecimal(vo.getTvmReconciliationAlipayB())));
                    //TVM对账微信
                    reviewVO.setTvmReconciliationWeChatB(ifNullDecimal(reviewVO.getTvmReconciliationWeChatB()).add(ifNullDecimal(vo.getTvmReconciliationWeChatB())));

                }
                ////////一二五九十四号线////////
                //支付宝差异
                reviewVO.setAlipayDifferenceA(ifNullDecimal(reviewVO.getTvmAlipayA()).subtract(ifNullDecimal(reviewVO.getTvmReconciliationAlipayA())));
                //微信差异
                reviewVO.setWeChatDifferenceA(ifNullDecimal(reviewVO.getTvmWeChatA()).subtract(ifNullDecimal(reviewVO.getTvmReconciliationWeChatA())));
                //差异合计
                reviewVO.setDiffSumA(ifNullDecimal(reviewVO.getAlipayDifferenceA().add(ifNullDecimal(reviewVO.getWeChatDifferenceA()))));

                ////////三四六号线////////
                //支付宝差异
                reviewVO.setAlipayDifferenceB(ifNullDecimal(reviewVO.getTvmAlipayB()).subtract(ifNullDecimal(reviewVO.getTvmReconciliationAlipayB())));
                //微信差异
                reviewVO.setWeChatDifferenceB(ifNullDecimal(reviewVO.getTvmWeChatB()).subtract(ifNullDecimal(reviewVO.getTvmReconciliationWeChatB())));
                //差异合计
                reviewVO.setDiffSumB(ifNullDecimal(reviewVO.getAlipayDifferenceB().add(ifNullDecimal(reviewVO.getWeChatDifferenceB()))));
                newList.add(reviewVO);
            }
        }
        //日期正序排序
        Collections.reverse(newList);
        return R.ok(newList);
    }

    /**
     * 导出
     * @param
     * @return
     */
    @ApiOperation(value = "导出", notes = "导出")
    @GetMapping({"/export"})
    @SysLog("ITVM分账户数据复核表-导出")
    @ApiImplicitParams(
            {
                    @ApiImplicitParam(name = "startDate", value = "开始日期：yyyy-MM-dd", dataTypeClass = String.class,required = true),
                    @ApiImplicitParam(name = "endDate", value = "结束日期：yyyy-MM-dd", dataTypeClass = String.class,required = true),
            }
    )
    public void export(String startDate,String endDate, HttpServletResponse response) throws Exception {
        if(StringUtils.isEmpty(startDate) ||  StringUtils.isEmpty(endDate)){
            return;
        }
        BigDecimal decimal100 = new BigDecimal("100");
        R<List<SwCkItvmSubAccountDataReviewVO>> data = this.getSwCkClearEmergencyReturnticketList(startDate, endDate);
        List<SwCkItvmSubAccountDataReviewVO> records = data.getData();
        for (SwCkItvmSubAccountDataReviewVO record : records) {
            record.setTvmAlipayA(record.getTvmAlipayA().divide(decimal100,2,BigDecimal.ROUND_HALF_UP));
            record.setTvmWeChatA(record.getTvmWeChatA().divide(decimal100,2,BigDecimal.ROUND_HALF_UP));
            record.setTvmReconciliationAlipayA(record.getTvmReconciliationAlipayA().divide(decimal100,2,BigDecimal.ROUND_HALF_UP));
            record.setTvmReconciliationWeChatA(record.getTvmReconciliationWeChatA().divide(decimal100,2,BigDecimal.ROUND_HALF_UP));
            record.setAlipayDifferenceA(record.getAlipayDifferenceA().divide(decimal100,2,BigDecimal.ROUND_HALF_UP));
            record.setWeChatDifferenceA(record.getWeChatDifferenceA().divide(decimal100,2,BigDecimal.ROUND_HALF_UP));
            record.setDiffSumA(record.getDiffSumA().divide(decimal100,2,BigDecimal.ROUND_HALF_UP));

            record.setTvmAlipayB(record.getTvmAlipayB().divide(decimal100,2,BigDecimal.ROUND_HALF_UP));
            record.setTvmWeChatB(record.getTvmWeChatB().divide(decimal100,2,BigDecimal.ROUND_HALF_UP));
            record.setTvmReconciliationAlipayB(record.getTvmReconciliationAlipayB().divide(decimal100,2,BigDecimal.ROUND_HALF_UP));
            record.setTvmReconciliationWeChatB(record.getTvmReconciliationWeChatB().divide(decimal100,2,BigDecimal.ROUND_HALF_UP));
            record.setAlipayDifferenceB(record.getAlipayDifferenceB().divide(decimal100,2,BigDecimal.ROUND_HALF_UP));
            record.setWeChatDifferenceB(record.getWeChatDifferenceB().divide(decimal100,2,BigDecimal.ROUND_HALF_UP));
            record.setDiffSumB(record.getDiffSumB().divide(decimal100,2,BigDecimal.ROUND_HALF_UP));
        }
        InputStream excelTemplateIs = null;
        try {
            response.reset(); // 非常重要
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            final String fileName = URLEncoder.encode("ITVM分账户数据复核表", "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + System.currentTimeMillis() + ".xlsx");

            // 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替
            // {} 代表普通变量 {.} 代表是list的变量
            excelTemplateIs = this.getClass().getResourceAsStream("/static/excel/template/export/SwCkItvmSubAccountDataReviewVOExcelTemplate.xlsx");

            ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).registerConverter(new LocalDateTimeConverter()).registerConverter(new LocalDateConverter()).withTemplate(excelTemplateIs).build();
            WriteSheet writeSheet = EasyExcel.writerSheet("ITVM分账户数据复核表").build();
            // 这里注意 入参用了forceNewRow 代表在写入list的时候不管list下面有没有空行 都会创建一行，然后下面的数据往后移动。默认 是false，会直接使用下一行，如果没有则创建。
            // forceNewRow 如果设置了true,有个缺点 就是他会把所有的数据都放到内存了，所以慎用
            // 简单的说 如果你的模板有list,且list不是最后一行，下面还有数据需要填充 就必须设置 forceNewRow=true 但是这个就会把所有数据放到内存 会很耗内存
            // 如果数据量大 list不是最后一行 参照另一个
            FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.FALSE).build();
            excelWriter.fill(records, fillConfig, writeSheet);
            excelWriter.finish();

        } catch (Exception e) {
            e.printStackTrace();
            LOGGER.error("导出ITVM分账户数据复核表异常");
        } finally {
            if(excelTemplateIs != null){
                try {
                    excelTemplateIs.close();
                } catch (IOException ioe) {
                    ioe.printStackTrace();
                }
            }
        }
    }

    /**
     * 校验null
     * @param amount
     * @return
     */
    private BigDecimal ifNullDecimal(BigDecimal amount) {
        if(amount == null){
            return new BigDecimal("0");
        }
        return amount;
    }
}
